/**
 * Full Application E2E Tests
 */

import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import userEvent from '@testing-library/user-event';

// Mock localStorage
const localStorageMock = {
  getItem: jest.fn(),
  setItem: jest.fn(),
  removeItem: jest.fn(),
  clear: jest.fn(),
};
Object.defineProperty(window, 'localStorage', { value: localStorageMock });

// Mock API responses
jest.mock('../../src/services/api', () => ({
  authApi: {
    login: jest.fn().mockResolvedValue({
      success: true,
      user: {
        user_id: 'test-user-123',
        email: 'test@example.com',
        name: 'Test User'
      },
      token: 'mock-jwt-token'
    }),
    getCurrentUser: jest.fn().mockResolvedValue({
      success: true,
      user: {
        user_id: 'test-user-123',
        email: 'test@example.com',
        name: 'Test User'
      }
    })
  },
  telemetryApi: {
    getTelemetryPoints: jest.fn().mockResolvedValue({
      success: true,
      data: [
        {
          id: 1,
          name: 'TestMetric1',
          type: 'histogram',
          component: 'TestComponent',
          analysis_status: 'NOT_ANALYZED'
        },
        {
          id: 2,
          name: 'TestMetric2',
          type: 'enum',
          component: 'TestComponent',
          analysis_status: 'ANALYZED'
        }
      ],
      total: 2
    }),
    getTelemetryStats: jest.fn().mockResolvedValue({
      success: true,
      data: {
        total_metrics: 150,
        by_type: { histogram: 75, enum: 75 },
        top_components: { Component1: 50, Component2: 25 }
      }
    }),
    updateAnalysisStatus: jest.fn().mockResolvedValue({
      success: true,
      message: 'Analysis status updated'
    })
  },
  teamApi: {
    getTeams: jest.fn().mockResolvedValue([
      {
        id: 'team-1',
        name: 'Team Alpha',
        description: 'First team',
        member_count: 5,
        assignment_count: 10
      },
      {
        id: 'team-2',
        name: 'Team Beta',
        description: 'Second team',
        member_count: 3,
        assignment_count: 7
      }
    ]),
    createTeam: jest.fn().mockResolvedValue({
      id: 'team-new',
      name: 'New Team',
      description: 'A new team',
      member_count: 0,
      assignment_count: 0
    })
  },
  searchApi: {
    search: jest.fn().mockResolvedValue({
      success: true,
      data: [
        {
          id: 1,
          name: 'TestMetric1',
          match_score: 0.95,
          match_fields: ['name']
        }
      ],
      total: 1
    }),
    getSearchSuggestions: jest.fn().mockResolvedValue({
      success: true,
      suggestions: ['TestMetric', 'TestComponent']
    })
  }
}));

// Mock React Query
jest.mock('react-query', () => ({
  QueryClient: jest.fn().mockImplementation(() => ({
    defaultOptions: {
      queries: { retry: false },
      mutations: { retry: false },
    },
  })),
  QueryClientProvider: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
  useQuery: jest.fn(),
  useMutation: jest.fn(),
}));

// Simplified full application component
const FullApp: React.FC = () => {
  const [isAuthenticated, setIsAuthenticated] = React.useState(false);
  const [currentView, setCurrentView] = React.useState('dashboard');
  const [teams, setTeams] = React.useState<any[]>([]);
  const [telemetryData, setTelemetryData] = React.useState<any[]>([]);

  const handleLogin = async () => {
    try {
      const { authApi } = require('../services/api');
      const response = await authApi.login();

      if (response.success) {
        localStorage.setItem('token', response.token);
        localStorage.setItem('user', JSON.stringify(response.user));
        setIsAuthenticated(true);
      }
    } catch (error) {
      console.error('Login failed:', error);
    }
  };

  const handleLogout = () => {
    localStorage.removeItem('token');
    localStorage.removeItem('user');
    setIsAuthenticated(false);
    setCurrentView('dashboard');
  };

  const loadDashboardData = async () => {
    try {
      const { telemetryApi, teamApi } = require('../services/api');
      const [telemetryResponse, teamsResponse] = await Promise.all([
        telemetryApi.getTelemetryStats(),
        teamApi.getTeams()
      ]);

      setTelemetryData(telemetryResponse.data?.by_type ? Object.entries(telemetryResponse.data?.by_type).map(([type, count]) => ({ type, count })) : []);
      setTeams(teamsResponse);
    } catch (error) {
      console.error('Failed to load dashboard data:', error);
    }
  };

  const loadTelemetryPoints = async () => {
    try {
      const { telemetryApi } = require('../services/api');
      const response = await telemetryApi.getTelemetryPoints();
      setTelemetryData(response.data);
    } catch (error) {
      console.error('Failed to load telemetry points:', error);
    }
  };

  const createNewTeam = async (teamData: any) => {
    try {
      const { teamApi } = require('../services/api');
      const response = await teamApi.createTeam(teamData);
      setTeams([...teams, response]);
    } catch (error) {
      console.error('Failed to create team:', error);
    }
  };

  const searchTelemetry = async (query: string) => {
    try {
      const { searchApi } = require('../services/api');
      const response = await searchApi.search({ query, filters: {} });
      setTelemetryData(response.data);
    } catch (error) {
      console.error('Failed to search telemetry:', error);
    }
  };

  React.useEffect(() => {
    if (isAuthenticated) {
      loadDashboardData();
    }
  }, [isAuthenticated]);

  if (!isAuthenticated) {
    return (
      <div data-testid="login-page">
        <h1>UmaInsight 平台</h1>
        <p>请登录以继续</p>
        <button onClick={handleLogin} data-testid="login-button">
          登录
        </button>
      </div>
    );
  }

  return (
    <div data-testid="app">
      <header data-testid="header">
        <h1>UmaInsight</h1>
        <nav data-testid="navigation">
          <button
            data-testid="nav-dashboard"
            onClick={() => setCurrentView('dashboard')}
            className={currentView === 'dashboard' ? 'active' : ''}
          >
            仪表板
          </button>
          <button
            data-testid="nav-telemetry"
            onClick={() => setCurrentView('telemetry')}
            className={currentView === 'telemetry' ? 'active' : ''}
          >
            遥测点
          </button>
          <button
            data-testid="nav-teams"
            onClick={() => setCurrentView('teams')}
            className={currentView === 'teams' ? 'active' : ''}
          >
            团队管理
          </button>
          <button
            data-testid="nav-search"
            onClick={() => setCurrentView('search')}
            className={currentView === 'search' ? 'active' : ''}
          >
            搜索
          </button>
        </nav>
        <button onClick={handleLogout} data-testid="logout-button">
          退出
        </button>
      </header>

      <main data-testid="main-content">
        {currentView === 'dashboard' && (
          <div data-testid="dashboard-view">
            <h2>仪表板</h2>
            <div data-testid="stats-container">
              <div data-testid="total-metrics">总遥测点: {telemetryData.reduce((sum, item) => sum + item.count, 0)}</div>
              <div data-testid="team-count">团队数量: {teams.length}</div>
            </div>
            <div data-testid="telemetry-chart">
              {telemetryData.map((item: any, index: number) => (
                <div key={index} data-testid={`metric-${item.type}`}>
                  {item.type}: {item.count}
                </div>
              ))}
            </div>
          </div>
        )}

        {currentView === 'telemetry' && (
          <div data-testid="telemetry-view">
            <h2>遥测点管理</h2>
            <div data-testid="telemetry-list">
              {telemetryData.map((item: any) => (
                <div key={item.id} data-testid={`telemetry-item-${item.id}`}>
                  <h3>{item.name}</h3>
                  <p>类型: {item.type}</p>
                  <p>状态: {item.analysis_status}</p>
                </div>
              ))}
            </div>
            <button onClick={loadTelemetryPoints} data-testid="refresh-telemetry">
              刷新数据
            </button>
          </div>
        )}

        {currentView === 'teams' && (
          <div data-testid="teams-view">
            <h2>团队管理</h2>
            <div data-testid="teams-list">
              {teams.map((team: any) => (
                <div key={team.id} data-testid={`team-${team.id}`}>
                  <h3>{team.name}</h3>
                  <p>{team.description}</p>
                  <p>成员数: {team.member_count}</p>
                </div>
              ))}
            </div>
            <button
              onClick={() => createNewTeam({ name: '新团队', description: '测试团队' })}
              data-testid="create-team-button"
            >
              创建团队
            </button>
          </div>
        )}

        {currentView === 'search' && (
          <div data-testid="search-view">
            <h2>搜索遥测点</h2>
            <input
              type="text"
              placeholder="搜索..."
              data-testid="search-input"
              onChange={(e) => {
                if (e.target.value.length > 2) {
                  searchTelemetry(e.target.value);
                }
              }}
            />
            <div data-testid="search-results">
              {telemetryData.map((item: any) => (
                <div key={item.id} data-testid={`search-result-${item.id}`}>
                  <h3>{item.name}</h3>
                  <p>匹配度: {item.match_score}</p>
                </div>
              ))}
            </div>
          </div>
        )}
      </main>
    </div>
  );
};

describe('Full Application E2E Tests', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    localStorageMock.clear();
  });

  describe('Complete User Journey', () => {
    test('complete user journey from login to data exploration', async () => {
      render(<FullApp />);

      // 1. Verify login page
      expect(screen.getByText('UmaInsight 平台')).toBeInTheDocument();
      expect(screen.getByText('请登录以继续')).toBeInTheDocument();
      expect(screen.getByTestId('login-button')).toBeInTheDocument();

      // 2. Login
      await userEvent.click(screen.getByTestId('login-button'));

      await waitFor(() => {
        expect(screen.getByTestId('app')).toBeInTheDocument();
        expect(screen.getByTestId('dashboard-view')).toBeInTheDocument();
      });

      // 3. Verify dashboard loaded
      expect(screen.getByText('仪表板')).toBeInTheDocument();
      expect(screen.getByTestId('stats-container')).toBeInTheDocument();
      expect(screen.getByTestId('telemetry-chart')).toBeInTheDocument();

      // 4. Test navigation
      const telemetryButton = screen.getByTestId('nav-telemetry');
      await userEvent.click(telemetryButton);
      expect(screen.getByTestId('telemetry-view')).toBeInTheDocument();

      const teamsButton = screen.getByTestId('nav-teams');
      await userEvent.click(teamsButton);
      expect(screen.getByTestId('teams-view')).toBeInTheDocument();

      const searchButton = screen.getByTestId('nav-search');
      await userEvent.click(searchButton);
      expect(screen.getByTestId('search-view')).toBeInTheDocument();

      const dashboardButton = screen.getByTestId('nav-dashboard');
      await userEvent.click(dashboardButton);
      expect(screen.getByTestId('dashboard-view')).toBeInTheDocument();

      // 5. Logout
      await userEvent.click(screen.getByTestId('logout-button'));
      expect(screen.getByTestId('login-page')).toBeInTheDocument();
    });

    test('can interact with telemetry data', async () => {
      render(<FullApp />);

      // Login
      await userEvent.click(screen.getByTestId('login-button'));

      await waitFor(() => {
        expect(screen.getByTestId('dashboard-view')).toBeInTheDocument();
      });

      // Navigate to telemetry
      const telemetryButton = screen.getByTestId('nav-telemetry');
      await userEvent.click(telemetryButton);
      expect(screen.getByTestId('telemetry-view')).toBeInTheDocument();

      // Refresh telemetry data
      const refreshButton = screen.getByTestId('refresh-telemetry');
      await userEvent.click(refreshButton);

      // Verify data is loaded
      await waitFor(() => {
        expect(screen.getByTestId('telemetry-list')).toBeInTheDocument();
        expect(screen.getAllByTestId(/telemetry-item-/).length).toBeGreaterThan(0);
      });
    });

    test('can create and manage teams', async () => {
      render(<FullApp />);

      // Login
      await userEvent.click(screen.getByTestId('login-button'));

      await waitFor(() => {
        expect(screen.getByTestId('dashboard-view')).toBeInTheDocument();
      });

      // Navigate to teams
      const teamsButton = screen.getByTestId('nav-teams');
      await userEvent.click(teamsButton);
      expect(screen.getByTestId('teams-view')).toBeInTheDocument();

      // Create new team
      const createButton = screen.getByTestId('create-team-button');
      await userEvent.click(createButton);

      // Verify team was created
      await waitFor(() => {
        expect(screen.getAllByTestId(/team-/).length).toBe(3); // 2 initial + 1 new
      });
    });

    test('can search and find telemetry data', async () => {
      render(<FullApp />);

      // Login
      await userEvent.click(screen.getByTestId('login-button'));

      await waitFor(() => {
        expect(screen.getByTestId('dashboard-view')).toBeInTheDocument();
      });

      // Navigate to search
      const searchButton = screen.getByTestId('nav-search');
      await userEvent.click(searchButton);
      expect(screen.getByTestId('search-view')).toBeInTheDocument();

      // Enter search query
      const searchInput = screen.getByTestId('search-input');
      await userEvent.type(searchInput, 'TestMetric');

      // Wait for search results
      await waitFor(() => {
        expect(screen.getByTestId('search-results')).toBeInTheDocument();
        expect(screen.getAllByTestId(/search-result-/).length).toBeGreaterThan(0);
      });
    });
  });

  describe('Application Reliability', () => {
    test('handles rapid navigation without crashes', async () => {
      render(<FullApp />);

      // Login
      await userEvent.click(screen.getByTestId('login-button'));

      await waitFor(() => {
        expect(screen.getByTestId('dashboard-view')).toBeInTheDocument();
      });

      // Rapid navigation
      const navButtons = [
        'nav-telemetry',
        'nav-teams',
        'nav-search',
        'nav-dashboard'
      ];

      for (let i = 0; i < 3; i++) { // Do 3 cycles of navigation
        for (const buttonId of navButtons) {
          const button = screen.getByTestId(buttonId);
          await userEvent.click(button);

          // Verify view changed
          const viewId = buttonId.replace('nav-', '') + '-view';
          expect(screen.getByTestId(viewId)).toBeInTheDocument();
        }
      }
    });

    test('maintains session during navigation', async () => {
      render(<FullApp />);

      // Login
      await userEvent.click(screen.getByTestId('login-button'));

      await waitFor(() => {
        expect(screen.getByTestId('dashboard-view')).toBeInTheDocument();
      });

      // Navigate through all views
      await userEvent.click(screen.getByTestId('nav-telemetry'));
      await userEvent.click(screen.getByTestId('nav-teams'));
      await userEvent.click(screen.getByTestId('nav-search'));

      // Should still be authenticated
      expect(screen.getByTestId('app')).toBeInTheDocument();
      expect(screen.getByTestId('logout-button')).toBeInTheDocument();
    });

    test('handles data loading states gracefully', async () => {
      render(<FullApp />);

      // Login
      await userEvent.click(screen.getByTestId('login-button'));

      await waitFor(() => {
        expect(screen.getByTestId('dashboard-view')).toBeInTheDocument();
      });

      // Navigate to views that load data
      const views = ['telemetry', 'teams', 'search'];

      for (const view of views) {
        const buttonId = `nav-${view}`;
        const button = screen.getByTestId(buttonId);
        await userEvent.click(button);

        // View should render even while data is loading
        const viewId = `${view}-view`;
        expect(screen.getByTestId(viewId)).toBeInTheDocument();
      }
    });
  });

  describe('Error Recovery', () => {
    test('recovers from temporary API failures', async () => {
      // Mock API failure then success
      const { telemetryApi } = require('../services/api');
      const originalGetTelemetryStats = telemetryApi.getTelemetryStats;
      telemetryApi.getTelemetryStats = jest.fn()
        .mockRejectedValueOnce(new Error('Network error'))
        .mockResolvedValueOnce({
          success: true,
          data: { total_metrics: 100 }
        });

      render(<FullApp />);

      // Login
      await userEvent.click(screen.getByTestId('login-button'));

      await waitFor(() => {
        expect(screen.getByTestId('dashboard-view')).toBeInTheDocument();
      });

      // Should recover from API failure and show data
      await waitFor(() => {
        expect(screen.getByTestId('stats-container')).toBeInTheDocument();
      });

      // Restore original function
      telemetryApi.getTelemetryStats = originalGetTelemetryStats;
    });

    test('handles storage quota exceeded gracefully', async () => {
      // Mock localStorage error
      localStorageMock.setItem.mockImplementation(() => {
        throw new Error('Storage quota exceeded');
      });

      render(<FullApp />);

      // Should still render without crashing
      const loginButton = screen.getByTestId('login-button');
      expect(loginButton).toBeInTheDocument();

      await userEvent.click(loginButton);

      // Should handle the error gracefully
      // In a real app, you'd show an error message
      expect(screen.getByTestId('app')).toBeInTheDocument();
    });
  });
});